﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestTasks
{
    public class TriangleClassifier
    {
        public class NotATriangleException : Exception { }
        
        public class TriangleProperties 
        {
            public bool IsAcuteAngled { get; set; }
            public bool IsObtuseAngled { get; set; }
            public bool IsRightAngled { get; set; }

            public bool IsIsosceles { get; set; }
            public bool IsEquilateral { get; set; }
        }

        
        readonly double epsilon;
        
        public TriangleClassifier(double epsilon) 
        {
            this.epsilon = epsilon;
        }

        /// <summary>
        /// a, b, c must be good: positive, not a NaN, epsilon and so on
        /// </summary>
        public TriangleProperties Classify(double a, double b, double c) 
        {
            checked
            {
                AssertEdge(a, b, c);
                AssertEdge(b, c, a);
                AssertEdge(c, a, b);

                return new TriangleProperties
                {
                    IsEquilateral = IsZero(a - b) && IsZero(a - c),
                    IsIsosceles = IsZero(a - b) || IsZero(a - c) || IsZero(b - c),
                    IsAcuteAngled = IsAcuteAngle(a, b, c) && IsAcuteAngle(b, c, a) && IsAcuteAngle(c, a, b),
                    IsObtuseAngled = IsObtuseAngled(a, b, c) || IsObtuseAngled(b, c, a) || IsObtuseAngled(c, a, b),
                    IsRightAngled = IsRightAngle(a, b, c) || IsRightAngle(b, c, a) || IsRightAngle(c, a, b),
                };
            }
        }

        
        void AssertEdge(double a, double b, double c) 
        {
            if (!IsPositive(b + c - a)) throw new NotATriangleException();
        }

        bool IsPositive(double value) 
        {
            return value > epsilon;
        }

        bool IsZero(double value)
        {
            return Math.Abs(value) <= epsilon;
        }

        bool IsRightAngle(double a, double b, double c)
        {
            return IsZero(a * a - b * b - c * c);
        }

        bool IsAcuteAngle(double a, double b, double c)
        {
            // based on law of cosines
            return IsPositive(b * b + c * c - a * a);
        }

        bool IsObtuseAngled(double a, double b, double c)
        {
            // based on law of cosines
            return IsPositive(a * a - b * b - c * c);
        }
    }
}
